package com.base.app_core.util.liteorm;

import android.database.Cursor;

import com.base.app_core.App;
import com.base.app_core.BuildConfig;
import com.base.app_core.service.user.model.User;
import com.base.app_core.util.log.F;
import com.litesuits.orm.LiteOrm;
import com.litesuits.orm.db.DataBaseConfig;
import com.litesuits.orm.db.annotation.Table;
import com.litesuits.orm.db.assit.QueryBuilder;
import com.litesuits.orm.db.impl.CascadeSQLiteImpl;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

;

/**
 * Created by ljs on 2016/6/3 0003.
 */

public class MyIChatDBHelpUtils implements Runnable {
    private static final String KACHEMAMA_DB_common = "common.db";//通用数据库
    private volatile LiteOrm mLiteOrm_common = null;
    private volatile LiteOrm mLiteOrm_user = null;//当前用户私有数据库
    private boolean isOpenUserDB = false;
    private ExecutorService mExecutor = null;// 线程池
    private ArrayList<DBHandleEvent> mDBHandleEvents = new ArrayList<>(50);
    User user;

    public void setUser(User user) {
        this.user = user;
    }

    public MyIChatDBHelpUtils() {
        getLiteOrm_common();
        getLiteOrm_Person();//打开私有数据库
        if (mExecutor == null)
            mExecutor = Executors.newSingleThreadExecutor();// 单个线程
        bThreadWorkflag = true;
        mExecutor.execute(this);
    }

    public Cursor getQueryBySql(Class cla, String sql, String[] args) {
        UseDBName mUseDBName = (UseDBName) cla.getAnnotation(UseDBName.class);
        LiteOrm _liteOrm = getLiteOrmByUseDBName(mUseDBName);
        return _liteOrm.querySQLCursor(cla, sql, args);
    }

    public void checkTableAndCreateByClass(Class... clas){
        F.j("myIchat check dbtable time="+ System.currentTimeMillis());
        for(Class cla:clas){
            UseDBName mUseDBName = (UseDBName) cla.getAnnotation(UseDBName.class);
            LiteOrm _liteOrm = getLiteOrmByUseDBName(mUseDBName);
            _liteOrm.createTableByClass(cla);
        }
        F.j("myIchat finish check dbtable time="+ System.currentTimeMillis());
    }
    public List QueryListDataBySql(final Class cla, String sql, String[] args) {
        UseDBName mUseDBName = (UseDBName) cla.getAnnotation(UseDBName.class);
        LiteOrm _liteOrm = getLiteOrmByUseDBName(mUseDBName);
        return ((CascadeSQLiteImpl) _liteOrm).getObjLstBySql(cla, sql, args);
    }

    /**
     * 查询所有
     *
     * @param cla
     * @return
     */
    public List getQueryAll(Class cla) {
        UseDBName mUseDBName = (UseDBName) cla.getAnnotation(UseDBName.class);
        LiteOrm _liteOrm = getLiteOrmByUseDBName(mUseDBName);
        return _liteOrm.query(cla);
    }

    public long getCountBySql(Class cla, String sql, String[] args) {
        UseDBName mUseDBName = (UseDBName) cla.getAnnotation(UseDBName.class);
        LiteOrm _liteOrm = getLiteOrmByUseDBName(mUseDBName);
        return _liteOrm.queryCoutBySql(cla, sql, args);
    }

    public int getCount(Class cla, String field, String[] value) {
        UseDBName mUseDBName = (UseDBName) cla.getAnnotation(UseDBName.class);
        LiteOrm _liteOrm = getLiteOrmByUseDBName(mUseDBName);
        QueryBuilder mquery = new QueryBuilder<Object>(cla);
        List valresult = null;
        if (field != null && field.length() != 0) {
            if (_liteOrm != null) {
                mquery.where(field, ((Object[]) value));
            }

            return (int) _liteOrm.queryCount(mquery);
        }
        return 0;
    }

    public String getTableKeyName(Class cla) {
        UseDBName mUseDBName = (UseDBName) cla.getAnnotation(UseDBName.class);
        LiteOrm _liteOrm = getLiteOrmByUseDBName(mUseDBName);
        return _liteOrm.getTableKeyName(cla);
    }

    public Object getFirstOBj(Class cla, String field, String[] value) {
        List _list = null;
        UseDBName mUseDBName = (UseDBName) cla.getAnnotation(UseDBName.class);
        LiteOrm _liteOrm = getLiteOrmByUseDBName(mUseDBName);
        if (field != null && field.length() != 0)
            _list = _liteOrm.query(new QueryBuilder(cla).where(field, (Object[]) value));
        else
            _list = _liteOrm.query(cla);
        if (_list != null & _list.size() != 0)
            return _list.get(0);
        else
            return null;
    }

    public void addEvent(DBHandleEvent... _event) {
        for (DBHandleEvent even : _event) {
            if (_event != null) {
                //if (even.getUseDBName() == null || even.getUseDBName().value() != DBNameType.SCNAME) {//不是商城的bean
                //    doWork(even);//不进入队列
                //    continue;
                //}
                synchronized (this){
                    mDBHandleEvents.add(even);
                    this.notify();
                }
            }
        }
    }
    public LiteOrm getLiteOrm_common() {
        if (mLiteOrm_common == null) {
            String dbName=KACHEMAMA_DB_common;
//            if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//                dbName=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+KACHEMAMA_DB_common;
//            }
            synchronized (MyIChatDBHelpUtils.this){
                if(null==mLiteOrm_common){
                    mLiteOrm_common = LiteOrm.newCascadeInstance(new DataBaseConfig(App.getContext(), dbName, true, BuildConfig.VERSION_CODE, null));
                    mLiteOrm_common.setDebugged(BuildConfig.DEBUG);
                }
            }
        }
        return mLiteOrm_common;
    }
    public LiteOrm getLiteOrm_Person(){
        if(null==user||!user.getLogin())
            return null;
        if(null==mLiteOrm_user){
            synchronized (MyIChatDBHelpUtils.this){
                if(null==mLiteOrm_user){
                    mLiteOrm_user= LiteOrm.newCascadeInstance(new DataBaseConfig(App.getContext(),user.getMobile()+"db",true,BuildConfig.VERSION_CODE,null));
                    mLiteOrm_user.setDebugged(BuildConfig.DEBUG);
                }
            }
        }
        return mLiteOrm_user;
    }

    private String mCurUserDBKeyID = "";//当前用户信息数据库所引用的用户keyId



    /*根据bean的注解状态选择相对应的数据库操作对象*/
    public LiteOrm getLiteOrmByUseDBName(UseDBName _useDBName) {
        LiteOrm _liteOrm = null;
        if (_useDBName == null) {
            return getLiteOrm_common();
        }
        switch (_useDBName.value()) {
            case PERSON_DB://
                _liteOrm = getLiteOrm_Person();
                break;
            case COMMON_DB://用户通用数据库或者是用户私有数据库
                _liteOrm = getLiteOrm_common();
                break;
        }
        return _liteOrm;
    }

    public List queryData(Class _class, String wherearg, String[] argval, String orderColumn, int orderType, int lmstart, int lmend) {
        UseDBName mUseDBName = (UseDBName) _class.getAnnotation(UseDBName.class);
        LiteOrm _liteOrm = getLiteOrmByUseDBName(mUseDBName);
        QueryBuilder mquery = new QueryBuilder<Object>(_class);
        List valresult = null;
        if (wherearg != null && wherearg.length() != 0) {
            if (_liteOrm != null) {
                mquery.where(wherearg, (Object[]) argval);
                // valresult = mLiteOrm.query(new
                // QueryBuilder<Object>(_class).where(wherearg, argval));
            }
        }

        if (orderColumn != null && orderColumn.length() != 0) {
            if (orderType == DBHandleEvent.ORDER_ASC) {
                mquery.appendOrderAscBy(orderColumn);
            } else {
                mquery.appendOrderDescBy(orderColumn);
            }
        }
        if (lmstart != -1 && lmend != -1) {
            mquery.limit(lmstart, lmend);
        }

        if (_liteOrm != null)
            valresult = _liteOrm.query(mquery);
        return valresult;
    }

    public void doWork(DBHandleEvent _event) {
        if (_event != null) {
            LiteOrm _liteOrm = getLiteOrmByUseDBName(_event.getUseDBName());
            if (_liteOrm != null) {
                //执行拼接SQL语句
                if (_event.getnHandleType() == DBHandleEvent.DB_SQL) {
                    String[] s = _event.getStrargs();
                    if(s == null){
                        s = new String[]{};
                    }
                    _liteOrm.executeSql(_event.getBeanclass(),_event.getmSql(), s);
                    return;
                }
                switch (_event.getnHandleType()) {
                    case DBHandleEvent.OBJECT_SAVE:
                        if (_event.getmWherebuilder() != null) {
                            _liteOrm.update(_event.getmWherebuilder());
                            break;
                        }
                       // F.w(Log.getStackTraceString(new Throwable()));
                        F.j("type:DBHandleEvent.OBJECT_SAVE class:" + _event.getBeanclass().getSimpleName());

                        switch (_event.getnDataType()) {
                            case DBHandleEvent.DATA_OBJ:
                                if (_event.beanobj != null) {
                                    _liteOrm.save(_event.beanobj);
                                }
                                break;
                            case DBHandleEvent.DATA_ARRAY:
                                if (_event.beanList != null && _event.beanList.size() > 0) {
                                    F.j("type:DBHandleEvent.OBJECT_SAVE class:" + _event.getBeanclass().getSimpleName() + " size:" + _event.beanList.size());
                                    _liteOrm.save(_event.beanList);
                                }
                                break;
                        }
                        break;
                    case DBHandleEvent.OBJECT_INSERT:
                        switch (_event.getnDataType()) {
                            case DBHandleEvent.DATA_OBJ:
                                if (_event.beanobj != null) {
                                    _liteOrm.insert(_event.beanobj);
                                }
                                break;
                            case DBHandleEvent.DATA_ARRAY:
                                if (_event.beanList != null && _event.beanList.size() > 0) {
                                    F.j("type:DBHandleEvent.OBJECT_SAVE class:" + _event.getBeanclass().getSimpleName() + " size:" + _event.beanList.size());
                                    _liteOrm.insert(_event.beanList);
                                }
                                break;
                        }
                        break;
                    case DBHandleEvent.OBJECT_DELETE:
                        if (_event.getmWherebuilder() != null) {
                            //                            _liteOrm.delete(_event.getmWherebuilder());
                            Class c = _event.getBeanclass();
                            if (c == null)
                                c = _event.getmWherebuilder().getTableClass();
                            StringBuilder sb = new StringBuilder();
                            sb.append("delete from " + ((Table) c.getAnnotation(Table.class)).value());
                            sb.append(" where 1=1 ");
                            Object[] params = _event.getmWherebuilder().getWhereArgs();
                            String where = _event.getmWherebuilder().getWhere();
                            if (where != null && !where.trim().equals("") && where.indexOf("?") < 0 && where.indexOf("=") < 0) {
                                where = where + " = ? ";
                            }
                            F.j("------OBJECT_DELETE--------:" + where + "---:" + ((Table) c.getAnnotation(Table.class)).value());
                            if (where != null && !where.trim().equals("") && !where.trim().startsWith("=")) {
                                sb.append(" and " + where);
                                F.j("------OBJECT_DELETE------------sb.toString():" + sb.toString());
                                _liteOrm.getWritableDatabase().execSQL(sb.toString(), params == null ? new String[]{} : params);
                            }
                            break;
                        }
                        switch (_event.getnDataType()) {
                            case DBHandleEvent.DATA_OBJ:
                                if (_event.beanobj != null) {
                                    _liteOrm.delete(_event.beanobj);
                                }
                                break;
                            case DBHandleEvent.DATA_ARRAY:
                                if (_event.beanList != null && _event.beanList.size() > 0) {
                                    _liteOrm.delete(_event.beanList);
                                }
                                break;
                        }
                        break;
                    case DBHandleEvent.OBJECT_UPDATE:
                        switch (_event.getnDataType()) {
                            case DBHandleEvent.DATA_OBJ:
                                if (_event.beanobj != null)
                                    _liteOrm.update(_event.beanobj);
                                break;
                            case DBHandleEvent.DATA_ARRAY:
                                if (_event.beanList != null && _event.beanList.size() > 0)
                                    _liteOrm.update(_event.beanList);
                                break;
                        }
                        break;
                    case DBHandleEvent.CLEAR_TABLE:
                        if (_event.getmWherebuilder() == null)
                            _liteOrm.deleteAll(_event.getBeanclass());
                        else
                            _liteOrm.delete(_event.getmWherebuilder());
                        F.j("type:DBHandleEvent.CLEAR_TABLE class:" + _event.getBeanclass().getSimpleName());
                        break;
                }
            }
        }
    }

    private boolean bThreadWorkflag = false;

    @Override
    public void run() {
        while (bThreadWorkflag) {
            DBHandleEvent _event = null;
            try {
                synchronized (MyIChatDBHelpUtils.this) {
                    if (mDBHandleEvents.size() <= 0)
                        MyIChatDBHelpUtils.this.wait();// 等待生产者
                    _event = mDBHandleEvents.remove(0);
                }
                doWork(_event);
            } catch (InterruptedException _e) {
                _e.printStackTrace();
            }
        }
    }

    public List queryData(Class localVideoClass, String s, String[] strings, String createTime, int orderDesc) {
        return queryData(localVideoClass, s, strings, createTime, orderDesc, -1, -1);
    }
}
